package se.webbzon.boltzmann.battle.property;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import se.webbzon.boltzmann.battle.strategy.AbstractStrategy;

public class BattleProperty {
	
	// The name of the texture set of this battle property
	private final String characterTextureSetName;
	
	// The maximal health of this battle property
	private int maxHealth;
	
	// The health of this battle property
	private int health;
	
	// The maximal energy of this battle property
	private int maxEnergy;
	
	// The energy of this battle property
	private int energy;
	
	// The strategy of this battle property
	private AbstractStrategy strategy;
	
	// A list of all buffs for this battle property
	private final List<BattleBuff> buffs;
	
	// A collection of all listeners to this battle property
	private final Collection<BattlePropertyListener> listeners;
	
	/*============================================================
	Constructors
	============================================================*/
	
	/** Creates a new battle property. **/
	public BattleProperty(	String characterTextureSetName,
							int maxHealth, int health, 
							int maxEnergy, int energy, 
							AbstractStrategy strategy) {
		this.characterTextureSetName = characterTextureSetName;
		this.maxHealth = maxHealth;
		this.maxEnergy = maxEnergy;
		this.strategy = strategy;
		buffs = new ArrayList<BattleBuff>();
		listeners = new ArrayList<BattlePropertyListener>();
		
		setEnergy(energy);
		setHealth(health);
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Adds a listener to this battle property. **/
	public boolean addListener(BattlePropertyListener listener) {
		return listeners.add(listener);
	}
	
	/** Removes a listener from this battle property. **/
	public boolean removeListener(BattlePropertyListener listener) {
		return listeners.remove(listener);
	}
	
	/** Clears all listeners in this battle property. **/
	public void clearListener(BattlePropertyListener listener) {
		listeners.clear();
	}
	
	/** Returns the character texture set name of this battle property. **/
	public String getCharacterTextureSetName() {
		return characterTextureSetName;
	}
	
	/** Returns the strategy of this battle property. **/
	public AbstractStrategy getStrategy() {
		return strategy;
	}
	
	/** Sets the strategy of this battle property. **/
	public void setStrategy(AbstractStrategy strategy) {
		this.strategy = strategy;
		for (BattlePropertyListener listener : listeners)
			listener.onSetStrategy(this,strategy);
	}

	/** Returns the maximal health of this battle property. **/
	public int getMaxHealth() {
		return maxHealth;
	}

	/** Sets the maximal health of this battle property. **/
	public void setMaxHealth(int maxHealth) {
		this.maxHealth = maxHealth;
		for (BattlePropertyListener listener : listeners)
			listener.onSetMaxHealth(this,maxHealth);
	}

	/** Returns the health of this battle property. **/
	public int getHealth() {
		return health;
	}

	/** Sets the health of this battle property. **/
	public void setHealth(int health) {
		if (health > maxHealth)
			this.health = maxHealth;
		else if (health > 0)
			this.health = health;
		else
			this.health = 0;
		
		for (BattlePropertyListener listener : getListeners())
			listener.onSetHealth(this,health);
	}

	/** Returns the maximal energy of this battle property. **/
	public int getMaxEnergy() {
		return maxEnergy;
	}

	/** Sets the maximal energy of this battle property. **/
	public void setMaxEnergy(int maxEnergy) {
		this.maxEnergy = maxEnergy;
		for (BattlePropertyListener listener : getListeners())
			listener.onSetMaxEnergy(this,maxEnergy);
	}

	/** Returns the energy of this battle property. **/
	public int getEnergy() {
		return energy;
	}

	/** Sets the energy of this battle property. **/
	public void setEnergy(int energy) {
		if (energy > maxEnergy)
			this.energy = maxEnergy;
		else if (energy > 0)
			this.energy = energy;
		else
			this.energy = 0;
		for (BattlePropertyListener listener : getListeners())
			listener.onSetEnergy(this,energy);
	}
	
	/** Adds a buff to the battle property. **/
	public boolean addBuff(BattleBuff buff) {
		removeBuffType(buff.getType());
		if (buffs.add(buff)) {
			for (BattlePropertyListener listener : getListeners())
				listener.onBuffAdd(this,buff);
			return true;
		} else
			return false;
	}
	
	/** Removes a buff from the battle property. **/
	public boolean removeBuff(BattleBuff buff) {
		if (buffs.remove(buff)) {
			for (BattlePropertyListener listener : getListeners())
				listener.onBuffRemove(this,buff);
			return true;
		} else
			return false;
	}
	
	/** Removes a buff of a given type from the battle property. **/
	public boolean removeBuffType(BattleBuffType type) {
		BattleBuff remove = null;
		for (BattleBuff b : buffs) {
			if (b.getType() == type) {
				remove = b;
				break;
			}
		}
				
		if (remove != null)
			return removeBuff(remove);
		else
			return false;
	}
	
	/** Returns a collection of all buffs of this battle property. **/
	public List<BattleBuff> getBuffs() {
		return Collections.unmodifiableList(buffs);
	}
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** Returns a iteration safe array of all listeners. **/
	private BattlePropertyListener[] getListeners() {
		return listeners.toArray(new BattlePropertyListener[0]);
	}

}
